home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_11_12
/
splash
/
splash.cpp
< prev
next >
Wrap
Text File
|
1993-01-14
|
17KB
|
645 lines
/*
* Version 1.8
* Written by Jim Morris, jegm@sgi.com
* Kudos to Larry Wall for inventing SP
* Copyrights only exist on the regex stuff, and all
* have been left intact.
* The only thing I ask is that you let me know of any nifty fixes or
* additions.
* Credits:
* I'd like to thank Michael Golan <mg@Princeton.EDU> for his critiques
* and clever suggestions. Some of which have actually been implemented
*/
#include <iostream.h>
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#ifdef __TURBOC__
#pragma hdrstop
#endif
#include "splash.h"
//************************************************************
// VarString Implementation
//************************************************************
VarString& VarString::operator=(const char *s)
{
int nl= strlen(s);
if(nl+1 >= allocated) grow((nl-allocated)+allocinc);
assert(allocated > nl+1);
strcpy(a, s);
len= nl;
return *this;
}
VarString& VarString::operator=(const VarString& n)
{
if(this != &n){
if(n.len+1 >= allocated){ // if it is not big enough
# ifdef DEBUG
fprintf(stderr, "~operator=(VarString&) a= %p\n", a);
# endif
delete [] a; // get rid of old one
allocated= n.allocated;
allocinc= n.allocinc;
a= new char[allocated];
# ifdef DEBUG
fprintf(stderr, "operator=(VarString&) a= %p, source= %p\n", a, n.a);
# endif
}
len= n.len;
strcpy(a, n.a);
}
return *this;
}
void VarString::grow(int n)
{
if(n == 0) n= allocinc;
allocated += n;
char *tmp= new char[allocated];
strcpy(tmp, a);
#ifdef DEBUG
fprintf(stderr, "VarString::grow() a= %p, old= %p, allocinc= %d\n", tmp, a, allocinc);
fprintf(stderr, "~VarString::grow() a= %p\n", a);
#endif
delete [] a;
a= tmp;
}
void VarString::add(char c)
{
if(len+1 >= allocated) grow();
assert(allocated > len+1);
a[len++]= c; a[len]= '\0';
}
void VarString::add(const char *s)
{
int nl= strlen(s);
if(len+nl >= allocated) grow(((len+nl)-allocated)+allocinc);
assert(allocated > len+nl);
strcat(a, s);
len+=nl;
}
void VarString::add(int ip, const char *s)
{
int nl= strlen(s);
if(len+nl >= allocated) grow(((len+nl)-allocated)+allocinc);
assert(allocated > len+nl);
memmove(&a[ip+nl], &a[ip], (len-ip)+1); // shuffle up
memcpy(&a[ip], s, nl);
len+=nl;
assert(a[len] == '\0');
}
void VarString::remove(int ip, int n)
{
assert(ip+n <= len);
memmove(&a[ip], &a[ip+n], len-ip); // shuffle down
len-=n;
assert(a[len] == '\0');
}
//************************************************************
// SPString stuff
//************************************************************
// assignments
SPString& SPString::operator=(const SPString& n)
{
if(this == &n) return *this;
pstr= n.pstr;
return *this;
}
SPString& SPString::operator=(const substring& sb)
{
VarString tmp(sb.pt, sb.len);
pstr= tmp;
return *this;
}
// concatenations
SPString SPString::operator+(const SPString& s) const
{
SPString ts(*this);
ts.pstr.add(s);
return ts;
}
SPString SPString::operator+(const char *s) const
{
SPString ts(*this);
ts.pstr.add(s);
return ts;
}
SPString SPString::operator+(char c) const
{
SPString ts(*this);
ts.pstr.add(c);
return ts;
}
SPString operator+(const char *s1, const SPString& s2)
{
SPString ts(s1);
ts = ts + s2;
// cout << "s2[0] = " << s2[0] << endl; // gives incorrect error
return ts;
}
//************************************************************
// other stuff
//************************************************************
char SPString::chop(void)
{
int n= length();
if(n <= 0) return '\0'; // empty
char tmp= pstr[n-1];
pstr.remove(n-1);
return tmp;
}
int SPString::index(const SPString& s, int offset)
{
if(offset < 0) offset= 0;
for(int i=offset;i<length();i++){
if(strncmp(&pstr[i], s, s.length()) == 0) return i;
}
return -1;
}
int SPString::rindex(const SPString& s, int offset)
{
if(offset == -1) offset= length()-s.length();
else offset= offset-s.length()+1;
if(offset > length()-s.length()) offset= length()-s.length();
for(int i=offset;i>=0;i--){
if(strncmp(&pstr[i], s, s.length()) == 0) return i;
}
return -1;
}
SPString::substring SPString::substr(int offset, int len)
{
if(len == -1) len= length() - offset; // default use rest of string
if(offset < 0){
offset= length() + offset; // count from end of string
if(offset < 0) offset= 0; // went too far, adjust to start
}
return substring(*this, offset, len);
}
// this is private
// it shrinks or expands string as required
void SPString::insert(int pos, int len, const char *s, int nlen)
{
if(pos < length()){ // nothing to delete if not true
if((len+pos) > length()) len= length() - pos;
pstr.remove(pos, len); // first remove subrange
}else pos= length();
VarString tmp(s, nlen);
pstr.add(pos, tmp); // then insert new substring
}
int SPString::m(Regexp& r)
{
return r.match(*this);
}
int SPString::m(const char *pat, const char *opts)
{
int iflg= strchr(opts, 'i') != NULL;
Regexp r(pat, iflg?Regexp::nocase:0);
return m(r);
}
int SPString::m(Regexp& r, SPStringList& psl)
{
if(!r.match(*this)) return 0;
psl.reset(); // clear it first
Range rng;
for (int i=0; i<r.groups(); i++){
rng= r.getgroup(i);
psl.push(substr(rng.start(), rng.length()));
}
return r.groups();
}
int SPString::m(const char *pat, SPStringList& psl, const char *opts)
{
int iflg= strchr(opts, 'i') != NULL;
Regexp r(pat, iflg?Regexp::nocase:0);
return m(r, psl);
}
//
// I know! This is not fast, but it works!!
//
int SPString::tr(const char *sl, const char *rl, const char *opts)
{
if(length() == 0 || strlen(sl) == 0) return 0;
int cflg= strchr(opts, 'c') != NULL; // thanks Michael
int dflg= strchr(opts, 'd') != NULL;
int sflg= strchr(opts, 's') != NULL;
int cnt= 0, flen= 0;
SPString t;
unsigned char lstc= '\0', fr[256];
// build search array, which is a 256 byte array that stores the index+1
// in the search string for each character found, == 0 if not in search
memset(fr, 0, 256);
for(int i=0;i<strlen(sl);i++){
if(i && sl[i] == '-'){ // got a range
assert(i+1 < strlen(sl) && lstc <= sl[i+1]); // sanity check
for(unsigned char c=lstc+1;c<=sl[i+1];c++){
fr[c]= ++flen;
}
i++; lstc= '\0';
}else{
lstc= sl[i];
fr[sl[i]]= ++flen;
}
}
int rlen;
// build replacement list
if((rlen=strlen(rl)) != 0){
for(i=0;i<rlen;i++){
if(i && rl[i] == '-'){ // got a range
assert(i+1 < rlen && t[t.length()-1] <= rl[i+1]); // sanity check
for(char c=t[i-1]+1;c<=rl[i+1];c++) t += c;
i++;
}else t += rl[i];
}
}
// replacement string that is shorter uses last character for rest of string
// unless the delete option is in effect or it is empty
while(!dflg && rlen && flen > t.length()){
t += t[t.length()-1]; // duplicate last character
}
rlen= t.length(); // length of translation string
// do translation, and deletion if dflg (actually falls out of length of t)
// also squeeze translated characters if sflg
SPString tmp; // need this in case dflg, and string changes size
for(i=0;i<length();i++){
int off;
if(cflg){ // complement, ie if NOT in f
char rc= !dflg ? t[t.length()-1] : '\0'; // always use last character for replacement
if((off=fr[(*this)[i]]) == 0){ // not in map
cnt++;
if(!dflg && (!sflg || tmp.length() == 0 || tmp[tmp.length()-1] != rc))
tmp += rc;
}else tmp += (*this)[i]; // just stays the same
}else{ // in fr so substitute with t, if no equiv in t then delete
if((off=fr[(*this)[i]]) > 0){
off--; cnt++;